import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:dss_base/dss_base.dart';
import 'package:dss_base/utils/log_util.dart';
import 'package:url_launcher/url_launcher_string.dart';

import 'base_entity.dart';

typedef NetSuccessCallback = Function(dynamic data);
typedef ApiConvert<T> = T Function(dynamic data);
typedef ApiSuccessCallback<T> = Function(BaseEntity entity, T data);
typedef ApiFailureCallback = Function(int code, String msg);

/// 默认的错误
final BaseEntity _defaultErrorEntity = BaseEntity(
  Code.error.code,
  Code.error.msg,
  null,
);

/// 创建一个成功的结果
BaseEntity createSuccessEntity<T>(T? data) =>
    BaseEntity(Code.success.code, '', data);

class HttpUtil {
  HttpUtil._();

  static final HttpUtil _singleton = HttpUtil._();

  static HttpUtil get instance => _singleton;

  static const String tag = 'flutter_http_log';

  late final Dio _dio;
  late final Dio _dioUpload;

  late ApiFailureCallback defaultFailureCallback;

  /// 初始化Dio配置
  void init({
    required String baseUrl,
    required String languageKey,
    required Duration connectTimeout,
    required Duration receiveTimeout,
    required Duration sendTimeout,
    List<Interceptor>? interceptors,
  }) {
    CommonHeaderInterceptor.language_key = languageKey;

    _dio = Dio(
      BaseOptions(
        connectTimeout: connectTimeout,
        receiveTimeout: receiveTimeout,
        sendTimeout: sendTimeout,

        // dio默认json解析，这里指定返回UTF8字符串，自己处理解析。（可也以自定义Transformer实现）
        responseType: ResponseType.plain,
        validateStatus: (_) {
          // 不使用http状态码判断状态，使用AdapterInterceptor来处理（适用于标准REST风格）
          return true;
        },
        baseUrl: baseUrl,
        // 适用于post form表单提交
        contentType: Headers.formUrlEncodedContentType,
      ),
    );
    interceptors?.forEach((element) {
      _dio.interceptors.add(element);
    });

    _dioUpload = Dio(
      BaseOptions(
        connectTimeout: Duration(seconds: 30),
        receiveTimeout: Duration(seconds: 30),
        sendTimeout: Duration(seconds: 30),

        // dio默认json解析，这里指定返回UTF8字符串，自己处理解析。（可也以自定义Transformer实现）
        responseType: ResponseType.plain,
        validateStatus: (_) {
          // 不使用http状态码判断状态，使用AdapterInterceptor来处理（适用于标准REST风格）
          return true;
        },
        baseUrl: baseUrl,
        // 适用于post form表单提交
        // contentType: Headers.formUrlEncodedContentType,
      ),
    );
  }

  void downloadFile(String url, {String? fileName}) {
    // web.HTMLAnchorElement()
    //   ..href = url
    //   ..download = fileName ?? url.split('/').last
    //   ..click();
    // Best-effort open; on web this triggers browser handling, on mobile opens external app
    launchUrlString(url);
  }

  Future<BaseEntity> uploadFileForWeb(
    String url, {
    required List<int> value,
    required String filename,
  }) async {
    FormData formData = FormData.fromMap({
      'file': MultipartFile.fromBytes(value, filename: filename),
    });

    try {
      final response = await _dioUpload.post(url, data: formData);
      final String data = response.data.toString();
      Map<String, dynamic> map = json.decode(data);
      return BaseEntity.fromJson(map);
    } catch (e) {
      return _defaultErrorEntity;
    }
  }

  Future<BaseEntity> uploadFileForApp(
    String url, {
    required String path,
    required String filename,
  }) async {
    FormData formData = FormData.fromMap({
      'file': MultipartFile.fromFileSync(path, filename: filename),
    });

    try {
      Log.d('*** Request ***', tag: tag);
      Log.d('url: ${_dioUpload.options.baseUrl}$url', tag: tag);
      Log.d('path: $path', tag: tag);
      final response = await _dioUpload.post(
        url,
        data: formData,
      );
      final String data = response.data.toString();
      Map<String, dynamic> map = json.decode(data);
      final entity = BaseEntity.fromJson(map);
      Log.d('Response: ${json.encode(entity)}', tag: tag);
      return entity;
    } catch (e) {
      Log.d('Response 报错了: $e', tag: tag);
      return _defaultErrorEntity;
    }
  }

  /// 通用的返回数据的处理
  Future request<T>({
    required Future<BaseEntity> request,
    ApiConvert<T>? onConvert,
    required ApiSuccessCallback<T> onSuccess,
    required ApiFailureCallback onFailure,
  }) async {
    BaseEntity baseEntity = await request;
    if (baseEntity.isSuccess) {
      if (onConvert != null) {
        T data = onConvert(baseEntity.data);
        onSuccess(baseEntity, data);
      } else {
        onSuccess(baseEntity, baseEntity.data);
      }
    } else {
      onFailure(baseEntity.code, baseEntity.info ?? Code.failure.msg);
    }
  }

  /// 供外界调用 - GET
  Future<BaseEntity> get({
    required String url,
    Map<String, dynamic>? params,
    Map<String, dynamic>? headers,
  }) async {
    try {
      // 设置请求头（headers）
      Options options = Options(
        headers: headers, // 传入的 headers
      );
      Response response = await _dio.get(
        url,
        queryParameters: params,
        options: options,
      );
      final String data = response.data.toString();
      Map<String, dynamic> map = json.decode(data);
      return BaseEntity.fromJson(map);
    } catch (e) {
      Log.e(e.toString());
      return _defaultErrorEntity;
    }
  }

  /// 供外界调用 - POST
  Future<BaseEntity> post({
    required String url,
    dynamic params,
    Map<String, dynamic>? headers,
  }) async {
    try {
      // 设置请求头（headers）
      Options options = Options(
        headers: headers, // 传入的 headers
      );
      Response response = await _dio.post(url, data: params, options: options);
      final String data = response.data.toString();
      Map<String, dynamic> map = json.decode(data);
      return BaseEntity.fromJson(map);
    } catch (e) {
      Log.e(e.toString());
      return _defaultErrorEntity;
    }
  }
}
